﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Linq;
using System.ServiceProcess;
using System.Text;
using System.ServiceModel;
using System.ServiceModel.Description;
using Celeriq.Utilities;
using System.Configuration;
using System.IO;

namespace Celeriq.WinService
{
    public partial class PersistentService : ServiceBase
    {
        #region Class Members

        private Celeriq.Client.Interfaces.ISystemCore _core = null;

        #endregion

        #region Constructor

        public PersistentService()
        {
            InitializeComponent();
        }

        #endregion

        #region Service Events

        protected override void OnStart(string[] args)
        {
            //For Debugging...
            //System.Threading.Thread.Sleep(5000);

            this.Start();

        }

        protected override void OnStop()
        {
            //KillTimer();
            try
            {
                if (_core != null) _core.ShutDown();
            }
            catch (Exception ex)
            {
                Logger.LogError(ex);
            }

            Logger.LogDebug("Services Stopped");
        }

        protected override void OnShutdown()
        {
            base.OnShutdown();
            Logger.LogDebug("Services ShutDown");
            //KillTimer();
        }

        #endregion

        #region Methods

        public void Start()
        {
            Logger.LogDebug("Services Started Begin");

            try
            {
                #region Load the service into memory

                if (!Directory.Exists(Celeriq.Server.Interfaces.ConfigurationSettings.DataPath))
                    Directory.CreateDirectory(Celeriq.Server.Interfaces.ConfigurationSettings.DataPath);

                #region Primary Endpoint

                var primaryAddress = new Uri("net.tcp://localhost:1973/__celeriq_core");
                var service = new Celeriq.Server.Core.SystemCore();
                var primaryHost = new ServiceHost(service, primaryAddress);

                //Initialize the service
                var netTcpBinding = new NetTcpBinding();
                netTcpBinding.Security.Mode = SecurityMode.None;
                primaryHost.AddServiceEndpoint(typeof (Celeriq.Client.Interfaces.ISystemCore), netTcpBinding, string.Empty);
                primaryHost.Open();

                //Create Core Listener
                var primaryEndpoint = new EndpointAddress(primaryHost.BaseAddresses.First().AbsoluteUri);
                var primaryClient = new ChannelFactory<Celeriq.Client.Interfaces.ISystemCore>(netTcpBinding, primaryEndpoint);
                _core = primaryClient.CreateChannel();

                #endregion

                this.LoadEngine(service);

                Logger.LogDebug("Services Started End");

                #endregion

            }
            catch (Exception ex)
            {
                Logger.LogError(ex);
                throw;
            }
        }

        private void LoadEngine(Celeriq.Server.Core.SystemCore core)
        {
            try
            {
                //Load Server Object
                var baseAddress = new Uri("net.tcp://localhost:1973/__celeriq_engine");
                var serviceInstance = core.Manager;
                var host = new ServiceHost(serviceInstance, baseAddress);

                //Initialize the service
                var myBinding = new NetTcpBinding()
                {
                    MaxBufferSize = int.MaxValue,
                    MaxReceivedMessageSize = int.MaxValue,
                    MaxBufferPoolSize = int.MaxValue,
                    ReaderQuotas = new System.Xml.XmlDictionaryReaderQuotas()
                    {
                        MaxArrayLength = int.MaxValue,
                        MaxBytesPerRead = int.MaxValue,
                        MaxDepth = int.MaxValue,
                        MaxNameTableCharCount = int.MaxValue,
                        MaxStringContentLength = int.MaxValue,
                    }
                };
                myBinding.Security.Mode = SecurityMode.None;
                var endpoint = host.AddServiceEndpoint(typeof(Celeriq.Common.IDataModel), myBinding, host.BaseAddresses.First().AbsoluteUri);

                foreach (var op in endpoint.Contract.Operations)
                {
                    var dataContractBehavior = op.Behaviors.Find<DataContractSerializerOperationBehavior>();
                    if (dataContractBehavior != null)
                    {
                        dataContractBehavior.MaxItemsInObjectGraph = int.MaxValue;
                    }
                }

                //var behavior = host.Description.Behaviors.Find<ServiceDebugBehavior>();
                //behavior.IncludeExceptionDetailInFaults = true;

                host.Open();

            }
            catch (Exception ex)
            {
                Logger.LogError(ex);
                throw;
            }

        }

        #endregion

    }
}